﻿using Maltose.Cache;
using Maltose.Configuration;
using Maltose.DynamicToken;
using Newtonsoft.Json.Linq;
using System;

namespace Maltose.Authorization
{
    /// <summary>
    /// 管理用户登录会话 token的生成 依赖 reids 缓存 方便集群管理
    /// </summary>
    public class UserSession
    {
        /// <summary>
        /// 动态令牌生成
        /// </summary>
        readonly UseDynamicToken _DynamicToken;

        /// <summary>
        /// 获取加密密钥
        /// </summary>
        string encryptKey = UseConfigFactory.Json.Get<string>("DynamicTokenKey");

        /// <summary>
        /// 过期时间
        /// </summary>
        int expireTime = UseConfigFactory.Json.Get<int>("DynamicTokenTime");


        //实例对象
        static UserSession _Lazy;
        //锁
        static readonly object _lock = new object();

        /// <summary>
        /// 使用单例访问
        /// </summary>
        public static UserSession Instance
        {
            get
            {
                if (_Lazy == null)
                {
                    lock (_lock)
                    {
                        if (_Lazy == null)
                            _Lazy = new UserSession();
                        return _Lazy;
                    }
                }
                return _Lazy;
            }
        }

        /// <summary>
        /// 缓存token 项目目录:平台_用户ID
        /// </summary>
        const string UserTokenKey = "Maltose:UserToken:{0}_{1}";

        /// <summary>
        /// 缓存token固定token
        /// </summary>
        const string UserFixedTokenKey = "Maltose:UserToken:{0}";

        /// <summary>
        /// 管理用户登录会话
        /// </summary>
        public UserSession()
        {
            _DynamicToken = new UseDynamicToken(encryptKey, expireTime);
        }

        /// <summary>
        /// 创建一个 token 动态令牌
        /// </summary>
        /// <param name="platform">平台</param>
        /// <param name="user">用户信息</param>
        /// <returns></returns>
        public string CreateToken(UserSessionPlatform platform, UserSessionStore user)
        {
            var sKey = string.Format(UserTokenKey, platform, user.Members_Id);
            return _DynamicToken.CreateToken(sKey, user);
        }

        /// <summary>
        /// 创建一个 固定动态令牌 永久有效
        /// </summary>
        /// <param name="user"></param>
        public void CreateFixedToken(UserSessionStore user)
        {
            // Maltose:UserToken:0ad603adc9d6c84b4ba677fd00f9cb5b_10000
            var sKey = string.Format(UserFixedTokenKey, user.MemberToken);

            if (UseCache.Instance.KeyExists(sKey))
            {
                return;
            }
            UseCache.Instance.Add(sKey, user.ToJson());
        }

        /// <summary>
        /// 验证固定的短token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public TokenContent ValidateFixed(string token)
        {
            var key = string.Format(UserFixedTokenKey, token);
            var rs = new TokenContent()
            {
                Msg = "token无效",
                State = TokenContentStateType.ExpirePassOrInvalid,
                Token = ""
            };
            if (UseCache.Instance.KeyExists(key))
            {
                rs.Msg = "成功";
                rs.State = TokenContentStateType.OK;
                rs.Token = token;
            }
            return rs;
        }

        /// <summary>
        /// 判断当前token是否存在 如果存在则直接获取token 短token无效
        /// </summary>
        /// <param name="platform"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public TokenContent ValidateWithToken(UserSessionPlatform platform, UserSessionStore user)
        {
            var sKey = string.Format(UserTokenKey, platform, user.Members_Id);
            var tokenData = UseCache.Instance.Get(sKey);

            var content = new TokenContent();

            if (string.IsNullOrWhiteSpace(tokenData))
            {
                content.State = TokenContentStateType.ExpirePassOrInvalid;
                content.Msg = "token过期或者无效";
            }
            else
            {
                content.Token = JObject.Parse(tokenData)["Token"].ToString();
                content.State = TokenContentStateType.OK;
            }
            return content;
        }

        /// <summary>
        /// 判断当前token是否正确
        /// </summary>
        /// <param name="token"></param>
        /// <param name="validateType">验证时候是不是自动刷新新的token 并且保存旧的token 有效10分钟内</param>
        /// <param name="isFixed">是否主动判断是否是长token或者短token 如果token=32位 优先判断为短token</param>
        /// <returns></returns>
        public TokenContent Validate(string token, ValidateType validateType, bool isFixed = true)
        {
            if (isFixed)
            {
                if (token.Length == 32)
                {
                    return ValidateFixed(token);
                }
            }
            return _DynamicToken.Validate(token, validateType);
        }

        /// <summary>
        /// 获取用户ID
        /// </summary>
        /// <param name="token">token</param>
        /// <param name="isFixed">是否主动判断是否是长token或者短token 如果token=32位 优先判断为短token</param>
        /// <returns></returns>
        public int GetMemberId(string token, bool isFixed = true)
        {
            //  Maltose:UserToken:{0}_{1}
            //  Maltose:UserToken:{0}_{1}_新的guiid
            //  Maltose:UserToken:0299613a66a6c10d275fd5b048b74065


            if (isFixed)
            {
                if (token.Length == 32)
                {
                    return GetFixedMemberId(token);
                }
            }

            var rawKey = _DynamicToken.GetRealKey(token);
            if (string.IsNullOrWhiteSpace(rawKey))
            {
                return 0;
            }
            var id = rawKey.Split("_")[1];
            return Convert.ToInt32(id);
        }

        /// <summary>
        /// 获取固定token的id 短token
        /// </summary>
        /// <param name="token">短token</param>
        /// <returns></returns>
        public int GetFixedMemberId(string token)
        {
            var fixedKey = string.Format(UserFixedTokenKey, token);
            var value = UseCache.Instance.Get(fixedKey) ?? "0";
            return Convert.ToInt32(value);
        }

        /// <summary>
        /// 获取储存信息
        /// </summary>
        /// <param name="token"></param>
        /// <param name="isFixed">是否主动判断是否是长token或者短token 如果token=32位 优先判断为短token</param>
        /// <returns></returns>
        public UserSessionStore GetUserSessionStore(string token, bool isFixed)
        {
            if (isFixed)
            {
                if (token.Length == 32)
                {
                    var key = string.Format(UserFixedTokenKey, token);
                    var fvalue = UseCache.Instance.Get(key);
                    if (string.IsNullOrWhiteSpace(fvalue))
                    {
                        return new UserSessionStore();
                    }
                    return fvalue.JsonToObject<UserSessionStore>();
                }

            }
            return _DynamicToken.GetCustomData<UserSessionStore>(token);
        }


        /// <summary>
        /// 删除动态令牌
        /// </summary>
        /// <param name="token">删除存在的token</param>
        /// <returns></returns>
        public bool Delete(string token)
        {
            return _DynamicToken.Delete(token);
        }

    }


}
